﻿using System;
using System.Threading;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Logic;

namespace IQIGame.Onigao.GamePlay
{
    public interface IBaseBattleCommandView : IReusableClassWithFree
    {
        UniTask<bool> PlayUpdate(bool bExecuteNow);
        int executerID { get; set; }

        bool localCommand { get; }
    }

    public class BaseBattleCommandView<T> : IBaseBattleCommandView where T : BaseBattleCommand
    {
        public T command { get; set; }

        public int executerID { get; set; }
        public CancellationTokenSource cancel;

        public virtual bool localCommand => false;

        // 是否忽略等待子弹命中继续执行    
        protected virtual EBattleUpdateType commandType => EBattleUpdateType.Min;

        public async UniTask<bool> PlayUpdate(bool bForceExecute)
        {
            try
            {
                var rQueueCtrl = BattleManager.Instance.ctrl.queueCtrl;
                var bInWaitingHit = rQueueCtrl.InWaitingBulletHit();
                var bExecuteNow = bForceExecute || !bInWaitingHit;
                if (!bExecuteNow && this.commandType == EBattleUpdateType.SkillEffective)
                {
                    // 只有当前正在播放的timeline所在的skillpart的skilleffective才可以跳过等待直接执行，用来处理提前发射的子弹
                    var rUnit = BattleManager.Instance.ctrl.data.GetUnit(this.executerID);
                    var rTimelineComp = rUnit.GetComponent<BattleTimelineComponent>(ETComponentType.BattleTimelineComponent);
                    bExecuteNow = this.command is BattleCommand_SkillEffective rEffectiveCommand && rEffectiveCommand.part == rTimelineComp.curTimelinePart;
                }
                if (bExecuteNow)
                {
                    var rUnit = BattleManager.Instance.ctrl.data.GetUnit(this.executerID);
#if UNITY_EDITOR
                    EditorLog.AppendBattleCommandLog(this);
#endif
                    await this.OnPlayUpdate(rUnit);
                }
                else
                {
                    rQueueCtrl.AddWaitingAction(this);
                }
                return bExecuteNow;
            }
            catch (OperationCanceledException)
            {
                LogGame.Log("表现队列取消: " + this.executerID + this.command);
                return true;
            }
            catch (Exception e)
            {
                LogGame.LogError("表现序列执行报错，需要检查序列：" + e + "\n" + this.executerID + this.command + "\n" + e.StackTrace);
                return true;
            }
        }

#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
        protected virtual async UniTask OnPlayUpdate(UnitView unit)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
        {
        }

#if UNITY_EDITOR
        public override string ToString()
        {
            return $"Type:{this.GetType().Name.Replace("BattleCommandView_", "")}, executer:{this.executerID}";
        }
#endif
        public void Initialize(T command, int executerID, CancellationTokenSource cancel)
        {
            this.command = command;
            this.executerID = executerID;
            this.cancel = cancel;
            this.OnInitialize(command, executerID);
        }

        protected virtual void OnInitialize(T rCommand, int nExecuterID)
        {
        }

        public uint MaxStore => 20;

        public virtual void OnReset()
        {
            this.command = null;
            this.executerID = 0;
            this.cancel = null;
        }

        public virtual void Free()
        {
            ClassPool.PutAutoType(this);
        }
    }
}